<template>
    <div class="map-wrapper">
        <div class="map-toolbar">
            <!-- 输入框（带历史记录） -->
            <el-popover placement="bottom-start" :width="250" trigger="click" ref="popoverRef">
                <template #reference>
                    <el-input class="map-search-box" placeholder="经纬度坐标" suffix-icon="Search" size="small" v-model="_location" round></el-input>
                </template>
                <div v-if="_locations.length == 0">No data</div>
                <div v-if="_locations.length > 0" class="location-list">
                    <div v-for="(loc, index) in _locations" :key="index" class="location-item" @click.stop="onClickLocation(loc)">
                        <el-icon class="location-icon">
                            <Coordinate />
                        </el-icon>
                        <span class="location-text">
                            {{ `${loc.lng.toFixed(7)},${loc.lat.toFixed(7)}` }}
                        </span>
                        <el-icon class="delete-icon" @click.stop="handleDeleteLocation(index)">
                            <Close />
                        </el-icon>
                    </div>
                </div>
            </el-popover>

            <!-- 定位和截图按钮 -->
            <div class="map-btn-wrapper">
                <el-button :icon="Location" size="small" @click="handleJump()" plain>定位</el-button>
                <el-button :icon="FullScreen" size="small" @click="handleCapture()" plain>手工抓取</el-button>
                <el-button type="danger" :icon="MagicStick" size="small" @click="handleAutoCapture()" plain>自动抓取</el-button>
            </div>
        </div>
        <div class="tile-map-container" ref="container">
            <canvas id="mapCanvas" ref="fabricCanvas" class="fabric-canvas"></canvas>
        </div>
    </div>
    <!-- create remote dialog -->
    <el-dialog v-model="dialogFormVisible" title="经纬度列表" align-center width="300px" :before-close="handleBeforeClose">
        <el-input v-model="_capture_locations" style="width: 100%" :rows="18" type="textarea" placeholder="请输入经纬度列表" />
        <template #footer>
            <span class="dialog-footer">
                <el-button type="primary" @click="onAutoCapture"> 确定 </el-button>
                <el-button @click="showDialog(false)">取消</el-button>
            </span>
        </template>
    </el-dialog>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, inject } from 'vue';
import { fabric } from 'fabric';
import API from '@/js/api';
import throttle from 'lodash/throttle'; // 引入节流函数
import { Location, FullScreen, MagicStick } from '@element-plus/icons-vue';
import { parseLocation } from '@/js/utils/mapUtils';

const emit = defineEmits(['location']);
let vueApp = inject('vueApp');

// 定义 props
const props = defineProps({
    zoom: {
        type: Number,
        default: 19
    },
    tileSize: {
        type: Number,
        default: 256
    },
    defaultTileX: {
        type: Number,
        default: 426984
    },
    defaultTileY: {
        type: Number,
        default: 227030
    }
});

// Fabric.js 的对象
const container = ref(null); // 容器元素
const fabricCanvas = ref(null); // Fabric.js 画布元素
const canvas = ref(null); // Fabric.js 画布实例
const targetTileSize = 100; // 目标瓦片大小

// 绘制 tiles 所需要的数据
const scale = ref(1); // 当前缩放比例
const offsetX = ref(0); // 水平偏移量
const offsetY = ref(0); // 垂直偏移量
const isDragging = ref(false); // 是否正在拖拽
const startX = ref(0); // 拖拽起始 X 坐标
const startY = ref(0); // 拖拽起始 Y 坐标
const showTileInfo = ref(true); // 是否显示瓦片边框和坐标

// 缓存 X 和 Y 方向的坐标
const tileXCoordinates = new Map(); // 缓存 X 方向的坐标
const tileYCoordinates = new Map(); // 缓存 Y 方向的坐标

// 定义 tileMap，用于管理每个瓦片的 Fabric.Group 对象
const tileMap = ref(new Map());

// Set 用于跟踪当前正在加载的瓦片，避免并发加载同一个瓦片
const loadingTiles = ref(new Set());

// 定义跳转的经纬度坐标
const popoverRef = ref(null);
const _location = ref('');
const _locations = ref([]);

// 定义自动抓取的经纬度列表
// const _capture_locations = [
//     { lat: 39.8422195, lng: 116.6439899 },
//     { lat: 39.8445719, lng: 116.6452824 },
//     { lat: 39.8461769, lng: 116.6487293 },
//     { lat: 39.8436040, lng: 116.6522400 }
// ];
const _capture_locations = ref('');
let _capture_queue = null;

// 定义经纬度列表相关的成员
let dialogFormVisible = ref(false);

// 获取瓦片图片的 URL
const getTileUrl = (x, y, zoom) => {
    return API.api_url('LoadTileImage', {
        x: x,
        y: y,
        zoom: zoom
    });
};

// 获取或计算 X 方向的坐标
const getTileX = (x) => {
    if (tileXCoordinates.has(x)) {
        return tileXCoordinates.get(x);
    }
    const tileX = x * props.tileSize;
    tileXCoordinates.set(x, tileX);
    return tileX;
};

// 获取或计算 Y 方向的坐标
const getTileY = (y) => {
    if (tileYCoordinates.has(y)) {
        return tileYCoordinates.get(y);
    }
    const tileY = y * props.tileSize;
    tileYCoordinates.set(y, tileY);
    return tileY;
};

// 计算当前视口范围内的瓦片
const computeVisibleTiles = () => {
    const tiles = [];
    if (!container.value || !canvas.value) return tiles;

    // 获取容器的尺寸
    const containerWidth = container.value.clientWidth;
    const containerHeight = container.value.clientHeight;

    // 考虑缩放比例，计算实际视口范围
    const scaledWidth = containerWidth / scale.value;
    const scaledHeight = containerHeight / scale.value;

    // 计算当前视口的左上角和右下角坐标（基于画布的坐标系）
    const viewportLeft = -offsetX.value / scale.value;
    const viewportTop = -offsetY.value / scale.value;
    const viewportRight = viewportLeft + scaledWidth;
    const viewportBottom = viewportTop + scaledHeight;

    // 计算瓦片范围
    const minX = Math.floor(viewportLeft / props.tileSize);
    const maxX = Math.ceil(viewportRight / props.tileSize);
    const minY = Math.floor(viewportTop / props.tileSize);
    const maxY = Math.ceil(viewportBottom / props.tileSize);

    // 遍历范围内的瓦片
    for (let x = minX; x <= maxX; x++) {
        for (let y = minY; y <= maxY; y++) {
            tiles.push({ x, y });
        }
    }

    return tiles;
};

// Computed 计算当前可见的瓦片
const visibleTiles = computed(() => computeVisibleTiles());

// 函数：检查瓦片是否仍然可见
const isTileVisible = (x, y) => {
    return visibleTiles.value.some((tile) => tile.x === x && tile.y === y);
};

// 节流后的更新函数，避免频繁调用
const throttledUpdateVisibleTiles = throttle(() => {
    const tiles = visibleTiles.value;
    const currentVisibleKeys = new Set();

    tiles.forEach((tile) => {
        const tileKey = `${tile.x},${tile.y}`;
        currentVisibleKeys.add(tileKey);

        if (!tileMap.value.has(tileKey) && !loadingTiles.value.has(tileKey)) {
            // 如果 tileMap 中没有该瓦片，且当前不在加载中，加载并添加
            loadTile(tile.x, tile.y);
        } else if (tileMap.value.has(tileKey)) {
            // 如果瓦片已经存在，更新其位置和缩放
            const tileGroup = tileMap.value.get(tileKey);
            if (tileGroup) {
                const { x, y } = tileGroup.tileCoordinates;

                const tileLeft = getTileX(x);
                const tileTop = getTileY(y);
                const scaledLeft = tileLeft * scale.value + offsetX.value;
                const scaledTop = tileTop * scale.value + offsetY.value;

                tileGroup.set({
                    left: scaledLeft,
                    top: scaledTop,
                    scaleX: scale.value,
                    scaleY: scale.value
                });

                // 更新文本的字体大小
                tileGroup.forEachObject((obj) => {
                    if (obj.type === 'text') {
                        obj.set({
                            fontSize: 14 * scale.value
                        });
                    }
                });

                tileGroup.setCoords();
            }
        }
    });

    // 找出不在当前可见范围内的瓦片，并移除
    tileMap.value.forEach((tileGroup, tileKey) => {
        if (!currentVisibleKeys.has(tileKey)) {
            // 从 canvas 中移除 Group
            canvas.value.remove(tileGroup);
            // 从 tileMap 中删除
            tileMap.value.delete(tileKey);
        }
    });

    // 渲染画布
    canvas.value.renderAll();
}, 100); // 根据需要调整节流时间（毫秒）

// 加载单个瓦片，并添加到画布及 tileMap
const loadTile = async (x, y) => {
    const tileKey = `${x},${y}`;

    // 如果瓦片已经在 tileMap 中，或正在加载，则跳过
    if (tileMap.value.has(tileKey) || loadingTiles.value.has(tileKey)) {
        return;
    }

    // 将瓦片标记为正在加载
    loadingTiles.value.add(tileKey);

    try {
        const url = getTileUrl(x, y, props.zoom);
        const img = await new Promise((resolve) => {
            fabric.util.loadImage(url, (img) => {
                if (img) {
                    resolve(img);
                } else {
                    resolve(null); // 图片加载失败，返回 null
                }
            });
        });

        // 获取实际的整数坐标
        const tileLeft = getTileX(x);
        const tileTop = getTileY(y);

        // 计算缩放后的位置
        const scaledLeft = tileLeft * scale.value + offsetX.value;
        const scaledTop = tileTop * scale.value + offsetY.value;

        // 在加载完成后，检查瓦片是否仍然可见
        if (!isTileVisible(x, y)) {
            // 如果瓦片不再可见，则不添加到画布
            return;
        }

        // 创建 Fabric.js 对象
        const objects = [];

        if (img) {
            const tileImage = new fabric.Image(img, {
                left: 0, // 相对于 Group 的位置
                top: 0,
                scaleX: 1, // 初始缩放为 1，由 Group 控制整体缩放
                scaleY: 1,
                selectable: false,
                evented: false,
                type: 'tile',
                hasBorders: false,
                hasControls: false
            });
            objects.push(tileImage);
        }

        // 创建边框
        const border = new fabric.Rect({
            left: 0, // 相对于 Group 的位置
            top: 0,
            width: props.tileSize,
            height: props.tileSize,
            stroke: 'red',
            strokeWidth: 1,
            fill: 'transparent',
            selectable: false,
            evented: false,
            type: 'border',
            hasBorders: false,
            hasControls: false
        });
        objects.push(border);

        // 创建文本
        const text = new fabric.Text(`x:${x}, y:${y}`, {
            left: 5, // 相对于 Group 的位置
            top: 5,
            fontSize: 14,
            fill: 'red',
            selectable: false,
            evented: false,
            type: 'text',
            hasBorders: false,
            hasControls: false
        });
        objects.push(text);

        // 创建 Group，将图片（如果存在）、边框和文本组合在一起
        const tileGroup = new fabric.Group(objects, {
            left: scaledLeft,
            top: scaledTop,
            selectable: false,
            evented: false,
            hasBorders: false,
            hasControls: false
        });

        // 为 Group 添加坐标信息，便于后续更新
        tileGroup.tileCoordinates = { x, y };

        // 设置 Group 的缩放
        tileGroup.set({
            scaleX: scale.value,
            scaleY: scale.value
        });

        // 将 Group 添加到画布
        canvas.value.add(tileGroup);

        // 将 Group 存储到 tileMap 中
        tileMap.value.set(tileKey, tileGroup);
    } catch (error) {
        console.error(`Error loading tile (${x},${y}):`, error);
    } finally {
        // 从 loadingTiles 中移除当前瓦片
        loadingTiles.value.delete(tileKey);

        // 在加载完成后，再次检查瓦片是否仍然可见
        if (isTileVisible(x, y) && !tileMap.value.has(tileKey)) {
            // 如果仍然可见，但 Group 尚未添加（可能加载中被取消），重新加载
            loadTile(x, y);
        }
    }
};

// 更新可见瓦片
const updateVisibleTiles = () => {
    throttledUpdateVisibleTiles();
};

// 处理鼠标按下事件
const onMouseDown = (event) => {
    event.preventDefault(); // 禁用默认的鼠标选择行为
    isDragging.value = true;
    startX.value = event.clientX - offsetX.value;
    startY.value = event.clientY - offsetY.value;
};

// 处理鼠标移动事件
const onMouseMove = (event) => {
    if (isDragging.value) {
        event.preventDefault(); // 禁用默认的鼠标选择行为
        offsetX.value = event.clientX - startX.value;
        offsetY.value = event.clientY - startY.value;
        updateVisibleTiles();
    }
};

// 处理鼠标松开事件
const onMouseUp = () => {
    isDragging.value = false;
};

// 处理滚轮事件
const onWheel = (event) => {
    event.preventDefault();
    const delta = event.deltaY < 0 ? 1.1 : 0.9; // 缩放比例
    const newScale = scale.value * delta;

    // 限制缩放比例，避免过于精细
    if (newScale < 0.1 || newScale > 10) return;

    // 计算缩放中心点
    const rect = container.value.getBoundingClientRect();
    const mouseX = event.clientX - rect.left;
    const mouseY = event.clientY - rect.top;

    // 调整偏移量，使缩放中心点保持不变
    offsetX.value = mouseX - (mouseX - offsetX.value) * delta;
    offsetY.value = mouseY - (mouseY - offsetY.value) * delta;

    // 更新缩放比例
    scale.value = newScale;

    // 更新可见瓦片
    updateVisibleTiles();
};

// 初始化 Fabric.js 画布
const initFabricCanvas = () => {
    if (fabricCanvas.value) {
        const containerWidth = container.value.clientWidth;
        const containerHeight = container.value.clientHeight;

        // 设置画布尺寸
        fabricCanvas.value.width = containerWidth;
        fabricCanvas.value.height = containerHeight;

        // 初始化 fabric.Canvas
        canvas.value = new fabric.Canvas(fabricCanvas.value, {
            backgroundColor: 'gray',
            width: containerWidth,
            height: containerHeight,
            fireRightClick: true,
            stopContextMenu: true,
            selection: false // 禁用默认的选择行为
        });

        // 计算缩放比例，使瓦片显示为 targetTileSize 像素
        scale.value = targetTileSize / props.tileSize; // 计算缩放比例

        // 计算初始偏移量，使指定的瓦片位于屏幕中心
        calculateInitialOffset();

        // 初始加载可见瓦片
        updateVisibleTiles();
    }
};

// 计算初始偏移量，使指定的瓦片位于屏幕中心
const calculateInitialOffset = () => {
    if (container.value) {
        const containerWidth = container.value.clientWidth;
        const containerHeight = container.value.clientHeight;

        // 计算指定瓦片的中心坐标
        const tileCenterX = props.defaultTileX * props.tileSize + props.tileSize / 2;
        const tileCenterY = props.defaultTileY * props.tileSize + props.tileSize / 2;

        // 计算初始偏移量，使瓦片居中显示
        offsetX.value = Math.round(containerWidth / 2 - tileCenterX * scale.value); // 考虑缩放比例
        offsetY.value = Math.round(containerHeight / 2 - tileCenterY * scale.value); // 考虑缩放比例
    }
};

// 跳转到指定经纬度
const jumpToLatLng = (lat, lng) => {
    // 清空画布中的所有对象
    if (canvas.value) {
        canvas.value.clear();
    }

    // 清空 tileMap 和 loadingTiles
    tileMap.value.clear();
    loadingTiles.value.clear();

    // 计算瓦片坐标
    const { x, y } = lngLatToTile(lng, lat, props.zoom);

    // 计算瓦片的中心坐标
    const tileCenterX = x * props.tileSize + props.tileSize / 2;
    const tileCenterY = y * props.tileSize + props.tileSize / 2;

    // 恢复到默认的缩放比例
    scale.value = targetTileSize / props.tileSize; // 计算默认缩放比例

    // 计算偏移量，使瓦片居中显示
    const containerWidth = container.value.clientWidth;
    const containerHeight = container.value.clientHeight;
    offsetX.value = Math.round(containerWidth / 2 - tileCenterX * scale.value);
    offsetY.value = Math.round(containerHeight / 2 - tileCenterY * scale.value);

    // 更新可见瓦片
    updateVisibleTiles();
};

// 经纬度转瓦片坐标
const lngLatToTile = (lng, lat, zoom) => {
    const tileCount = Math.pow(2, zoom);
    const x = ((lng + 180) / 360) * tileCount;
    const y = ((1 - Math.log(Math.tan((lat * Math.PI) / 180) + 1 / Math.cos((lat * Math.PI) / 180)) / Math.PI) / 2) * tileCount;
    return { x: Math.floor(x), y: Math.floor(y) };
};

// 瓦片坐标转经纬度
const tileToLngLat = (x, y, zoom) => {
    const tileCount = Math.pow(2, zoom);
    const lng = (x / tileCount) * 360 - 180;
    const lat = (Math.atan(Math.sinh(Math.PI * (1 - (2 * y) / tileCount))) * 180) / Math.PI;
    return { lng, lat };
};

// 处理鼠标点击事件
const onMouseClick = (event) => {
    const rect = container.value.getBoundingClientRect();
    const mouseX = event.clientX - rect.left;
    const mouseY = event.clientY - rect.top;

    // 计算点击位置在画布上的坐标
    const canvasX = (mouseX - offsetX.value) / scale.value;
    const canvasY = (mouseY - offsetY.value) / scale.value;

    // 计算对应的瓦片坐标
    const tileX = Math.floor(canvasX / props.tileSize);
    const tileY = Math.floor(canvasY / props.tileSize);

    // 计算瓦片内的像素坐标
    const pixelX = canvasX - tileX * props.tileSize;
    const pixelY = canvasY - tileY * props.tileSize;

    // 转换为经纬度
    const { lng, lat } = tileToLngLat(tileX + pixelX / props.tileSize, tileY + pixelY / props.tileSize, props.zoom);

    // 输出经纬度
    // console.log(`点击位置的经纬度: (${lng}, ${lat})`);
    emit('location', { lng: lng.toFixed(7), lat: lat.toFixed(7) });
    _location.value = `${lng.toFixed(7)},${lat.toFixed(7)}`;
    // alert(`点击位置的经纬度: (${lng}, ${lat})`);
};

function onClickLocation(loc) {
    // console.log('onClickLocation loc = ', loc);
    if (popoverRef.value) {
        popoverRef.value.hide();
    }

    _location.value = `${loc.lng},${loc.lat}`;
    handleJump();
}

function saveLocation(lng, lat) {
    const roundedLng = parseFloat(lng.toFixed(1));
    const roundedLat = parseFloat(lat.toFixed(1));

    // 获取已保存的经纬度数组
    const savedLocations = JSON.parse(localStorage.getItem('savedLocations')) || [];

    // 检查是否已经保存过
    const isDuplicate = savedLocations.some((loc) => parseFloat(loc.lng.toFixed(1)) === roundedLng && parseFloat(loc.lat.toFixed(1)) === roundedLat);

    if (!isDuplicate) {
        savedLocations.push({ lng: lng, lat: lat });
        _locations.value = savedLocations;
        localStorage.setItem('savedLocations', JSON.stringify(savedLocations));
    }
}

function handleDeleteLocation(index) {
    console.log(`handleDeleteLocation index = `, index);
    if (popoverRef.value) {
        popoverRef.value.hide();
    }

    _locations.value.splice(index, 1);
    localStorage.setItem('savedLocations', JSON.stringify(_locations.value));
}

function handleJump() {
    try {
        const { lng, lat } = parseLocation(_location.value);
        _location.value = `${lng},${lat}`;
        saveLocation(lng, lat);
        jumpToLatLng(lat, lng);
    } catch (error) {
        ElMessage.error(error.message);
    }
}

// 自动截图的处理函数，每次从capture_queue中pop一个进行实际截图
async function autoCapture() {
    try {
        if (_capture_queue.length > 0) {
            let loc = _capture_queue.pop();

            // 打开窗口，设置mode是自动
            let result = await API.local.invoke('NewMapWnd', {
                position: JSON.stringify({
                    lat: loc.lat,
                    lng: loc.lng,
                    zoom: 19,
                    mode: 'auto'
                })
            });

            // 返回结果
            console.log(result);
            if (result.code != 0) {
                ElMessage.error(result.msg);
            }
        } else {
            ElMessage('自动截图队列中已经没有数据！');
        }
    } catch (error) {
        ElMessage.error(error.message);
    }
}

async function onWsMessage(message) {
    console.log('MapTiles::onWsMessage message = ', message);
    let data = JSON.parse(message);
    if (data.event === 'close') {
        await autoCapture();
    }
}

// 判断并解析经纬度列表
function parseLocations(locationStr) {
    let locationArray = locationStr.split('\n');
    // console.log(locationArray);
    try {
        let locs = [];
        for (let i = 0; i < locationArray.length; i++) {
            const { lng, lat } = parseLocation(locationArray[i]);
            locs.push({
                lng,
                lat
            });
        }
        return locs;
    } catch (error) {
        ElMessage.error(error.message);
        return [];
    }
}

async function onAutoCapture() {
    _capture_queue = parseLocations(_capture_locations.value);
    // console.log(_capture_queue);
    showDialog(false);
    await autoCapture();
}

function showDialog(show) {
    dialogFormVisible.value = show;
    vueApp.monitorKeyEvent(!show);
}

function handleBeforeClose(done) {
    vueApp.monitorKeyEvent(true);
    done();
}

async function handleAutoCapture() {
    showDialog(true);
}

async function handleCapture() {
    try {
        // 获取当前的经纬度坐标
        const { lng, lat } = parseLocation(_location.value);
        _location.value = `${lng},${lat}`;
        saveLocation(lng, lat);

        // 打开窗口，设置mode是手工还是自动
        let result = await API.local.invoke('NewMapWnd', {
            position: JSON.stringify({
                lat: lat,
                lng: lng,
                zoom: 19,
                mode: 'manual'
            })
        });
        console.log(result);
        if (result.code != 0) {
            ElMessage.error(result.msg);
        }
    } catch (error) {
        ElMessage.error(error.message);
    }
}

// 组件挂载时初始化
onMounted(() => {
    const containerEl = container.value;
    if (!containerEl) {
        console.error('Container element is not mounted');
        return;
    }

    const canvasEl = fabricCanvas.value;
    if (!canvasEl) {
        console.error('Canvas element is not mounted');
        return;
    }

    // 读取locations记录
    _locations.value = JSON.parse(localStorage.getItem('savedLocations')) || [];

    // 绑定事件
    containerEl.addEventListener('mousedown', onMouseDown);
    containerEl.addEventListener('mousemove', onMouseMove);
    containerEl.addEventListener('mouseup', onMouseUp);
    containerEl.addEventListener('wheel', onWheel, { passive: false }); // 确保 passive 为 false
    containerEl.addEventListener('click', onMouseClick); // 绑定点击事件

    // 初始化 Fabric.js 画布
    initFabricCanvas();
});

// 组件卸载时清理
onBeforeUnmount(() => {
    const containerEl = container.value;
    if (containerEl) {
        containerEl.removeEventListener('mousedown', onMouseDown);
        containerEl.removeEventListener('mousemove', onMouseMove);
        containerEl.removeEventListener('mouseup', onMouseUp);
        containerEl.removeEventListener('wheel', onWheel);
        containerEl.removeEventListener('click', onMouseClick);
    }

    // 销毁 Fabric.js 画布
    if (canvas.value) {
        canvas.value.dispose();
    }

    // 清空 tileMap 和 loadingTiles
    tileMap.value.clear();
    loadingTiles.value.clear();
});

defineExpose({ onWsMessage });
</script>

<style scoped>
.tile-map-container {
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;
}

.fabric-canvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: all;
}

.map-wrapper {
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: block;
}

.map-toolbar {
    display: flex;
    background-color: rgb(249, 248, 248);
    align-items: center;
    padding: 10px;
    width: 100%;
    height: 40px;
    box-sizing: border-box;
}

.map-search-box {
    width: 250px;
    border-radius: 10px;
}

.map-btn-wrapper {
    display: flex;
    position: absolute;
    right: 10px;
}

.location-list {
    max-height: 250px;
    overflow-y: auto;
}

.location-item {
    display: flex;
    align-items: center;
    padding: 8px;
    cursor: pointer;
}

.location-item:hover {
    background-color: #f5f7fa;
}

.location-icon {
    margin-right: 8px;
    color: #409eff;
}

.location-text {
    flex: 1;
    margin-right: 8px;
}

.delete-icon {
    color: #f56c6c;
    cursor: pointer;
}

.delete-icon:hover {
    color: #ff7875;
}
</style>
